#include "mymalloc.h"
#include "usart.h"

void my_meminit(void);
u8 my_mem_perused(void);

// 内存设备管理结构体
my_mem_dev mem_dev = {
    .init = my_meminit,
    .perused = my_mem_perused,
    .membank = NULL,
    .memman = NULL,
    .memrdy = 0,
};

// 内存拷贝(按字节)
void my_memcpy(void *dest, void * src,u32 size)
{
    u8 * dest_p = dest;
    u8 * src_p = src;
    while(size--) 
        *dest_p++ = *src_p++;
}

// 内存设置
void my_memset(void * mem,u8 n,u32 size)
{
    u8 * mem_p = mem;
    while(size--)
        *mem_p++ = n;
}


// 初始化内存池
void my_meminit(void)
{
    my_memset(mem_dev.membank,0,MEM_BANK_SIZE);
    my_memset(mem_dev.memman,0,MEM_ITEM_NUM * 2);
    mem_dev.memrdy = 1;
}

// 统计内存使用率(%)
u8 my_mem_perused(void)
{
    u16 used = 0;
    u32 i;
    for(i = 0; i < MEM_ITEM_NUM; i++)
    {
        if(mem_dev.memman[i]) used++;
    }
    return used*100/MEM_ITEM_NUM;
}


// 底层分配内存(返回地址偏移)
// size: 申请空间的大小
// 返回0xFFFFFFFF表示出错
u32 mem_malloc(u32 size)
{
    signed long offset = 0;
    u16 nmemb,cnemb = 0;
    u32 i;
    if(size==0) return 0xFFFFFFFF; // 不需要分配
    if(!mem_dev.memrdy) mem_dev.init();
    // 计算总共占用的块数
    nmemb = size / MEM_BLOCK_SIZE;
    if(size  % MEM_BLOCK_SIZE) nmemb++;
    // 从后往前分配空间
    for(offset=MEM_ITEM_NUM-1; offset>=0; offset--)
    {
        if(!mem_dev.memman[offset]) cnemb++;
        else cnemb = 0;
        if(cnemb == nmemb) // 找到连续可分配的内存
        {
            for(i = 0; i < nmemb; i++)
            {
                mem_dev.memman[offset+i] = nmemb;
            }
            return (offset * MEM_BLOCK_SIZE);
        }
    }
    return 0xFFFFFFFF;
}

// 底层释放内存函数
// 返回0,释放成功
// 返回1,释放失败
// 返回2,地址偏移错误
u8 mem_free(u32 offset)  
{  
    int i;  
    if(!mem_dev.memrdy)//未初始化,先执行初始化
    {
        mem_dev.init();    
        return 1;//未初始化  
    }  
    if(offset<MEM_BANK_SIZE)//偏移在内存池内. 
    {  
        int index=offset/MEM_BLOCK_SIZE;//偏移所在内存块号码  
        int nmemb=mem_dev.memman[index];   //内存块数量
        // 清零空间中的数据(按块)
        my_memset(&mem_dev.membank[offset],0,nmemb*MEM_BLOCK_SIZE);
        for(i=0;i<nmemb;i++)     //内存块清零
        {  
            mem_dev.memman[index+i]=0;  
        }  
        return 0;  
    }else return 2;//偏移超区了.  
}  

// 分配函数
void * mymalloc(u32 size)
{
    u32 offset;
    offset = mem_malloc(size);
    if(offset == 0xFFFFFFFF) return NULL;
    else return (void *)(mem_dev.membank+offset);
}

// 释放函数
void myfree(void * ptr)
{
    u32 offset;
    if(ptr==NULL) return;
    offset = (u32)ptr - (u32)mem_dev.membank;
    mem_free(offset);
}

// 重新分配空间
void * myrealloc(void *ptr,u32 size)  
{  
    u32 offset;  
    offset=mem_malloc(size);  
    if(offset==0XFFFFFFFF)return NULL;     
    else  
    {  
        my_memcpy(&mem_dev.membank[offset],ptr,size);//拷贝旧内存内容到新内存   
        myfree(ptr);               //释放旧内存
        return &mem_dev.membank[offset];      //返回新内存首地址
    }  
}
